package com.nxw.springcloud.gateway.config;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.validation.Validator;
import reactor.core.publisher.Mono;

import java.util.List;

@Configuration
public class GatewayServiceConfig {
 
    @Bean
    @ConditionalOnMissingBean
    @Primary
    public RedisRateLimiter redisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate, @Qualifier("redisRequestRateLimiterScript") RedisScript<List<Long>> redisScript, @Qualifier("defaultValidator") Validator validator) {
        return new RedisRateLimiter(redisTemplate, redisScript, validator);
    }
 
    @Bean
    @Primary
    public RateKeyResolver rateKeyResolver() {
        return new RateKeyResolver();
    }
 
    @Bean(name = "rateRedisRateLimiter")
    public RateRedisRateLimiter rateRedisRateLimiter(ReactiveRedisTemplate<String, String> redisTemplate,
                                                    @Qualifier(RateRedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript<List<Long>> redisScript,
                                                    @Qualifier("defaultValidator") Validator validator) {
        return new RateRedisRateLimiter(redisTemplate, redisScript, validator);
    }

    @Bean
    KeyResolver apiKeyResolver() {
        //按URL限流,即以每秒内请求数按URL分组统计
        return exchange -> Mono.just(exchange.getRequest().getPath().toString());
    }

    @Bean
    public RateLimiterGatewayFilterFactory rateLimiterGatewayFilterFactory(
            @Qualifier("rateRedisRateLimiter") RateRedisRateLimiter rateRedisRateLimiter,
            RateKeyResolver rateKeyResolver) {
        return new RateLimiterGatewayFilterFactory(rateRedisRateLimiter, rateKeyResolver);
    }
}